home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: redoPageDeallocation.c,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/05/04 21:55:57 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
-
-
- #include "sysdefs.h"
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "pool.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "thread.h"
- #include "latch.h"
- #include "semaphore.h"
- #include "link.h"
- #include "lsn.h"
- #include "bf.h"
- #include "log.h"
- #include "volume.h"
- #include "logrecs.h"
- #include "trans.h"
- #include "bitmap.h"
- #include "openlog.h"
- #include "logaction.h"
- #include "io_extfuncs.h"
- #include "io_logfuncs.h"
- #include "bf_extfuncs.h"
- #include "bm_extfuncs.h"
- #include "trans_extfuncs.h"
- #include "redo_extfuncs.h"
- #include "util_funcs.h"
- #include "thread_globals.h"
- #include "log_globals.h"
- #include "log_extfuncs.h"
- #include "distr.h"
- #include "distr_globals.h"
- #include "distr_extfuncs.h"
-
-
- void
- redoPageDeallocation (
-
- LOGRECORDHDR *record
- )
- {
-
- register VOLREC *volRec;
- register PID *pid;
- register int i;
- register GROUPLINK *groupLink;
- register DIRTYPAGEINFO *dirtyInfo;
- BITMAPPAGE *bitmapPage;
- PID bitmapPid;
- PID volHdrPid;
- LRC *lrcList;
- int bitmapPageCount;
- int deallocPageCount; /* # of pages allocated */
- LRC *headerLRC; /* volume header lrc */
- SHORTPID allocPage;
- int bitsToSet; /* # bits to set on page*/
- int totalBitsToSet;
- int bitsSetSoFar;
- int bit;
- PAGEALLOCINFO *pageAllocInfo;
- TRANSREC *transRec;
-
-
- TRPRINT(TR_IO|TR_LOG, TR_LEVEL_1, ("lsn:%d", record->recordLSN.offset));
-
- /*
- * Initially the volume info is unknown
- */
- volRec = NULL;
-
- /*
- * get a pointer to the common page deallocation info
- */
- pageAllocInfo = (PAGEALLOCINFO *) GET_LOG_IMAGE(record, 0);
- TRPRINT(TR_IO|TR_LOG, TR_LEVEL_2, ("numPages:%d", pageAllocInfo->numPages));
-
- /*
- * get a pointer to the name in the record and the number
- * of pages allocated
- */
- pid = (PID *) GET_LOG_IMAGE(record, 1);
- deallocPageCount = GET_LOG_IMAGE_SIZE(record, 1) / sizeof(PID);
- SM_ASSERT(LEVEL_3, pageAllocInfo->numPages == deallocPageCount);
- TRPRINT(TR_IO|TR_LOG, TR_LEVEL_2, ("pid:%d", pid->page));
-
- /*
- * - for distr trans
- * check if the transaction is one which is in prepared state
- */
- if ((transRec = findDistrTransRec(record->tid, &ServerDistrTransList)) != NULL) {
- /*
- * just reconstruct the list - don't do the deallocation
- * NOTE: pass in PAGE_GENERIC as the type because
- * io_FakeDeallocPages converts slotted pages to
- * normal ones - we don't want to do this here
- * because we would already have done that when
- * we encountered the log record for the conversion
- */
- if (io_FakeDeallocPages(pageAllocInfo->page2size,
- pageAllocInfo->numPages,
- pid,
- &(transRec->pageDeallocList),
- PAGE_GENERIC) != esmNOERROR) {
-
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- }
-
- /*
- * return success
- */
- return;
- }
-
- /*
- * get a pointer to the lrc list for the bitmap pages, and
- * calculate the number of bitmap pages involved, base on
- * the length of the list
- */
- lrcList = (LRC *) GET_LOG_IMAGE(record, 2);
- bitmapPageCount = GET_LOG_IMAGE_SIZE(record, 2) / sizeof(LRC);
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("lrc list size:%d", bitmapPageCount));
-
- /*
- * get a pointer to the volume header lrc
- */
- headerLRC = &(pageAllocInfo->headerLRC);
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("header lrc:%d", headerLRC->count));
-
- /*
- * Remove all the dealloced pages from the buffer pool
- */
- for (i = 0; i < deallocPageCount; i++) {
- bf_InvalidatePage(pid+i);
- }
-
- /*
- * set the volume id of the bitmap pid
- */
- bitmapPid.volid = pid->volid;
-
- /*
- * check the pages for the dirty list
- */
- allocPage = pid->page; /* first allocated page */
- totalBitsToSet = deallocPageCount * BLOCKCOUNT(pageAllocInfo->page2size);
- bitsSetSoFar = 0;
- for (i = 0; i < bitmapPageCount; i++) {
-
- /*
- * calculate the bitmap page
- */
- bitmapPid.page = BIT_TO_PAGE(allocPage) + pageAllocInfo->firstBitmapPage;
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("bitmap page:%d", bitmapPid.page));
-
- /*
- * The number of bits to set is either the number left on
- * the bitmap page or the number of pages left to mark
- * allocated, whichever is smaller.
- */
- bitsToSet = (int) MIN((BITS_IN_PAGE - BIT_IN_PAGE(allocPage)),
- (totalBitsToSet - bitsSetSoFar) );
- bitsSetSoFar += bitsToSet;
- SM_ASSERT(LEVEL_3, deallocPageCount >= (allocPage - pid->page));
-
- /*
- * check to see if the page is in the dirty list
- */
- if ((dirtyInfo = searchDirtyPageTable( &bitmapPid )) == NULL) {
-
- /*
- * don't need to redo the entry
- */
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("page not in table"));
- continue;
- }
-
- /*
- * check to see if the lrc on the page is greater than
- * the lrc in the log record
- */
- if (CHECK_PAGE_LRC_LESS_DIRTYINFO(lrcList[i], record->recordLSN, dirtyInfo)) {
- /*
- * don't need to redo
- */
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty info page lrc later"));
- continue;
- }
-
- /*
- * check to see if the volume is mounted
- */
- if (volRec == NULL) {
- if ((volRec = io_FindVolRec(pid->volid)) == NULL) {
-
- SM_ERROR(TYPE_FATAL, Active->errno);
- }
- SM_ASSERT(LEVEL_3, pageAllocInfo->firstBitmapPage == volRec->header->freeBitmapAddr);
- }
-
- /*
- * read in the page
- */
- if ((groupLink = bf_ReadPage(volRec->bufGroup, &bitmapPid,
- BITMAP_PAGE2SIZE, BF_SEM)) == NULL) {
-
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- }
-
- /*
- * get a pointer to the bitmap page
- */
- bitmapPage = (BITMAPPAGE *) groupLink->bufFrame;
-
- /*
- * check to see if the lrc on the page is greater than
- * the lrc in the log record
- */
- if (compareLRC( &(lrcList[i]), &(bitmapPage->lrc)) <= 0) {
-
- /*
- * don't need to redo
- * mark the page lrc
- */
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("actual page lrc later"));
- dirtyInfo->lrc = bitmapPage->lrc;
-
- /*
- * release the page, not dirty
- */
- signalSemaphore( &(groupLink->pageHash->semaphore) );
- bf_UnfixPage(groupLink, BF_DEFAULT, FALSE);
- continue;
- }
-
- /*
- * clear all necessary bits for this bitmap page
- */
- for (bit = (int) BIT_IN_PAGE(allocPage);
- bit < (BIT_IN_PAGE(allocPage)+bitsToSet); bit++) {
-
- /*
- * actually set the bit
- */
- bm_SetBit((UFOUR *) groupLink->bufFrame, (FOUR) BIT_IN_PAGE(bit));
- }
-
- /*
- * set the page lrc
- * Set up the firstLSN/LRC for the page
- */
- bitmapPage->lrc = lrcList[i];
- DEPEND_LOG(groupLink->pageHash, 0, &(record->recordLSN), (lrcList+i));
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("marking new page lrc:%d", bitmapPage->lrc.count));
-
- /*
- * free and dirty the page
- */
- signalSemaphore( &(groupLink->pageHash->semaphore) );
- bf_UnfixPage(groupLink, BF_DEFAULT, TRUE);
-
- /*
- * Calculate index of the first allocated page on the next
- * bitmap page.
- */
- allocPage += BITS_IN_PAGE - BIT_IN_PAGE(allocPage);
- }
- SM_ASSERT(LEVEL_3, totalBitsToSet == bitsSetSoFar);
-
- /*
- * Redo the increment to the numFreePages field on the volume
- * header if necessary. First, get the header page pid.
- */
- volHdrPid.page = HEADERADDR;
- volHdrPid.volid = pid->volid;
-
- /*
- * check to see if the page is in the dirty page list
- */
- if ((dirtyInfo = searchDirtyPageTable(&volHdrPid)) == NULL) {
-
- /*
- * don't need to redo
- */
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty page not present"));
- return;
- }
-
- if (volRec == NULL) {
- if ((volRec = io_FindVolRec(volHdrPid.volid)) == NULL) {
-
- SM_ERROR(TYPE_FATAL, Active->errno);
- }
- SM_ASSERT(LEVEL_3, pageAllocInfo->firstBitmapPage == volRec->header->freeBitmapAddr);
- }
-
- #ifdef DEBUG
- /*
- * check to see if the lrc on the page is greater than
- * the lrc in the log record
- * NOTE: this comparison is not strictly necessary, since the
- * header page is always resident and the next comparison
- * count be made instead.
- */
- if (compareLRC( headerLRC, &(dirtyInfo->lrc) ) < 0) {
-
- /*
- * don't need to redo
- */
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty info page lrc later"));
- return;
- }
-
- /*
- * Make sure the comparison was correct
- */
- SM_ASSERT(LEVEL_3, compareLSN( &(record->recordLSN), &(dirtyInfo->lsn)) >= 0);
- #endif DEBUG
-
- /*
- * check to see if the lrc on the header page is greater than
- * the lrc in the log record
- */
- if (compareLRC( headerLRC, &volRec->header->lrc) <= 0) {
-
- /*
- * don't need to redo
- * mark the page lrc, and return
- */
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("actual page lrc later"));
- dirtyInfo->lrc = volRec->header->lrc;
-
- return;
- }
-
- /*
- * The volume header needs to be updated, so increment the number
- * of free pages by the number deallocated.
- */
- if (waitSemaphore(&(volRec->headerLink->pageHash->semaphore)) != esmNOERROR) {
- SM_ERROR(TYPE_FATAL, esmNOERROR);
- }
- io_ChangeVolFreePages(volRec, totalBitsToSet);
-
- /*
- * mark the LRC on the header page and dirty the page
- * Set up the firstLSN/LRC for the page
- * release the semaphore on the volume header
- */
- volRec->header->lrc = *headerLRC;
- DEPEND_LOG(volRec->headerLink->pageHash, 0, &(record->recordLSN), headerLRC);
- TRPRINT(TR_RECOVER, TR_LEVEL_2, ("marking header page lrc:%d", volRec->header->lrc.count));
- signalSemaphore(&(volRec->headerLink->pageHash->semaphore));
-
- return;
- }
-